# 导入必要的库
import ctypes
import tkinter as tk
from tkinter import scrolledtext, ttk, filedialog, messagebox
import pandas as pd
import os
import re
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

from core.workflow import Workflow
import core.functions as func

class TableFrame(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.parent = parent
        self.data = None
        self.columns = []
        self.header_frame = None
        self.content_frame = None
        self.row_frames = []
        self.highlighted_col_index = -1
        self.bg_color = '#f0f0f0'
        self.header_color = '#e0e0e0'
        self.highlight_color = 'yellow'

    def clear(self):
        # 清空表格
        for widget in self.winfo_children():
            widget.destroy()
        self.row_frames = []
        self.columns = []
        self.data = None
        self.highlighted_col_index = -1

    def set_data(self, df):
        self.clear()
        self.data = df
        self.columns = df.columns.tolist()
        self.index_name = df.index.name or '索引'

        # 创建表头
        self.header_frame = tk.Frame(self, bg=self.header_color)
        self.header_frame.pack(fill=tk.X)

        # 创建数据列标题
        for col_idx, col in enumerate(self.columns):
            header_label = tk.Label(self.header_frame, text=col, padx=10, pady=5, bg=self.header_color, borderwidth=1, relief=tk.SOLID)
            header_label.grid(row=0, column=col_idx, sticky='nsew')
            # 设置列权重
            self.header_frame.grid_columnconfigure(col_idx, weight=1, minsize=40)

        # 创建一个可滚动的数据区域
        self.data_frame = tk.Frame(self)
        self.data_frame.pack(fill=tk.BOTH, expand=True)

        # 插入数据行
        for row_idx, (index, row) in enumerate(df.iterrows()):
            row_frame = tk.Frame(self.data_frame, bg=self.bg_color)
            row_frame.pack(fill=tk.X)
            self.row_frames.append(row_frame)

            # 为行设置交替背景色
            bg_color = '#ffffff' if row_idx % 2 == 0 else '#f9f9f9'

            # 添加数据单元格
            for col_idx, col in enumerate(self.columns):
                value = row[col]
                if pd.isna(value):
                    value = ''
                cell_label = tk.Label(row_frame, text=str(value), padx=10, pady=3, bg=bg_color, borderwidth=1, relief=tk.SOLID)
                cell_label.grid(row=0, column=col_idx, sticky='nsew')
                # 设置列权重
                row_frame.grid_columnconfigure(col_idx, weight=1, minsize=40)

        # 绑定窗口大小变化事件
        self.parent.bind('<Configure>', self.on_resize)

    def on_resize(self, event=None):
        # 当窗口大小变化时，调整表格宽度
        if self.header_frame:
            width = self.winfo_width()
            for col_idx in range(len(self.columns)):
                self.header_frame.grid_columnconfigure(col_idx, weight=1, minsize=max(50, width//len(self.columns)))
                for row_frame in self.row_frames:
                    row_frame.grid_columnconfigure(col_idx, weight=1, minsize=max(50, width//len(self.columns)))

    def highlight_column(self, col_name, highlight_color='yellow'):
        # 重置高亮
        self.highlighted_col_index = -1
        
        # 重置表头背景色
        if self.header_frame:
            for widget in self.header_frame.winfo_children():
                widget.config(bg=self.header_color)
        
        # 重置数据行背景色
        for row_frame in self.row_frames:
            for widget in row_frame.winfo_children():
                # 恢复默认背景色
                row_idx = self.row_frames.index(row_frame)
                bg_color = '#ffffff' if row_idx % 2 == 0 else '#f9f9f9'
                widget.config(bg=bg_color)

        # 查找匹配的列
        if col_name in self.columns:
            # 高亮数据列
            col_idx = self.columns.index(col_name)
            self.highlighted_col_index = col_idx

            # 高亮表头
            if self.header_frame:
                header_label = self.header_frame.grid_slaves(row=0, column=col_idx)[0]
                header_label.config(bg=highlight_color)

            # 高亮数据单元格
            for row_frame in self.row_frames:
                cell_label = row_frame.grid_slaves(row=0, column=col_idx)[0]
                cell_label.config(bg=highlight_color)
            return True
        return False


class MainWindow:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("锋衡")

        # 设置窗口大小
        # screen_width = self.root.winfo_screenwidth()
        # screen_height = self.root.winfo_screenheight()
        # width = int(screen_width * 0.7)
        # height = int(screen_height * 0.7)
        # x = (screen_width - width) // 2
        # y = (screen_height - height) // 2
        # self.root.geometry(f"{width}x{height}+{x}+{y}")

        try:
            ctypes.windll.shcore.SetProcessDpiAwareness(1)
            scale_factor = ctypes.windll.shcore.GetScaleFactorForDevice(0) / 100
            self.root.tk.call('tk', 'scaling', scale_factor * 1.333)
        except:
            pass

        self.current_col_index = -1 # 记录当前的列索引

        self.workflow = Workflow()  # 实例化流程

        ########## 生成主界面并划分区域 ##########

        # main_frame
        self.main_frame = tk.Frame(self.root)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 左侧的workflow_frame
        self.workflow_frame = tk.Frame(self.main_frame)
        self.workflow_frame.pack(side=tk.LEFT, padx=(0, 30))
        # 右侧区域
        self.right_frame = tk.Frame(self.main_frame)
        self.right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        # 裁决表区域
        self.table_frame = tk.Frame(self.right_frame)
        self.table_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=False)

        # 裁决表下方区域
        self.bottom_frame = tk.Frame(self.right_frame)
        self.bottom_frame.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True, pady=(10, 0), ipady=5)
        # 裁决输出
        self.chat_frame = tk.Frame(self.bottom_frame)
        self.chat_frame.pack(side=tk.LEFT, fill=tk.Y, expand=False, padx=(0, 5))
        # 按钮区域
        self.buttons_frame = tk.Frame(self.bottom_frame)
        self.buttons_frame.pack(side=tk.LEFT, anchor=tk.N, padx=20)

        ########## ########## ########## ########## 

        # 加载界面控件
        self.load_workflow_frame()
        self.load_table_frame()
        self.load_chat_frame()
        self.load_buttons_frame()

        # 根据控件占据的空间自动设置窗口大小
        self.root.update()
        width = max(w.winfo_reqwidth() for w in self.root.winfo_children())
        height = sum(w.winfo_reqheight() for w in self.root.winfo_children())
        self.root.geometry(f"{width + 20}x{height + 20}+0+0")
        
        # 初始化流程图
        self.workflow.plot_workflow()
        self.canvas.draw()

        # 输出欢迎信息
        self.welcome_message()

#### 初始化相关函数 ###########################################################

    def load_workflow_frame(self):

        # 标题
        self.process_label = tk.Label(self.workflow_frame, text="裁决规则流程指示")
        self.process_label.pack(anchor=tk.W, pady=(5, 5))

        ####################################################

        # frame[workflow_menue + manage_workflow_button]
        self.manage_frame = tk.Frame(self.workflow_frame)
        self.manage_frame.pack(fill=tk.X, pady=(5, 5))
        # 流程选择下拉菜单
        self.workflow_var = tk.StringVar(value=list(self.workflow.dict.keys())[0])
        self.workflow_menu = ttk.Combobox(self.manage_frame, textvariable=self.workflow_var, values=list(self.workflow.dict.keys()))
        self.workflow_menu.pack(side=tk.LEFT)
        self.workflow_menu.bind("<<ComboboxSelected>>", self.workflow_menu_change)
        # 流程管理按钮
        self.manage_workflow_button = tk.Button(self.manage_frame, text="规则管理", command=self.manage_workflow)
        self.manage_workflow_button.pack(side=tk.RIGHT, padx=(5, 0))
        
        ####################################################

        # frame[canvas]
        self.canvas_frame = tk.Frame(self.workflow_frame)
        self.canvas_frame.pack(fill=tk.BOTH, expand=False)
        # 配置画布
        self.canvas = FigureCanvasTkAgg(self.workflow.fig, master=self.canvas_frame)
        self.canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=False)

        ####################################################

        # frame[prev_button + next_button]
        self.control_frame = tk.Frame(self.workflow_frame)
        self.control_frame.pack(fill=tk.X, pady=(5, 5))
        self.prev_button = tk.Button(self.control_frame, text="上一步", width=8, command=self.prev_button_click)
        self.prev_button.pack(side=tk.LEFT, pady=(5, 0), padx=(0, 5))
        self.next_button = tk.Button(self.control_frame, text="下一步", width=8, command=self.next_button_click)
        self.next_button.pack(side=tk.RIGHT, pady=(5, 0), padx=(5, 0))

    def load_table_frame(self):
        # 标题和导入按钮
        self.a_frame = tk.Frame(self.table_frame)
        self.a_frame.pack(fill=tk.X, pady=(0, 5))
        self.a_label = tk.Label(self.a_frame, text="裁决表")
        self.a_label.pack(side=tk.LEFT, anchor=tk.W)
        self.import_btn = tk.Button(
            self.a_frame, 
            text="导入", 
            command=self.import_btn_click, 
            width=8, 
            height=1
        )
        self.import_btn.pack(side=tk.RIGHT, padx=10)

        # 创建一个临时的空白标签，用于占位，防止表格区域太小
        self.blank_label = tk.Label(self.table_frame, text="", height=8)
        self.blank_label.pack()  
        
        # 创建Notebook组件用于标签页显示
        self.notebook = ttk.Notebook(self.table_frame)
        self.notebook.pack(fill=tk.BOTH, expand=True, pady=0)
        # 配置标签页样式
        style = ttk.Style()
        style.configure("TNotebook.Tab", width=15)  
        # 存储各sheet的数据和表格组件
        self.sheets_data = {}
        self.sheet_tables = {}

    def load_chat_frame(self):
        self.b_label = tk.Label(self.chat_frame, text="裁决输出")
        self.b_label.pack(anchor=tk.W, pady=(0, 10))
        self.b_text = scrolledtext.ScrolledText(self.chat_frame, wrap=tk.WORD, width=60)
        self.b_text.pack(side=tk.LEFT, anchor=tk.W, fill=tk.Y, expand=True)
        self.b_text.see(tk.END)  # 设置滚动条默认在最下方

    def load_buttons_frame(self):
        
        # 0.标题
        self.title_label = tk.Label(self.buttons_frame, text="条件输入")
        self.title_label.pack(side=tk.TOP, anchor=tk.W, padx=10, pady=(0, 5))

        # 1.兵力比
        self.ratio_frame = tk.Frame(self.buttons_frame)
        self.ratio_frame.pack(side=tk.TOP, anchor=tk.W, padx=10, pady=5)
        self.ratio_label = tk.Label(self.ratio_frame, text="兵力比:")
        self.ratio_label.pack(side=tk.LEFT, padx=(0, 5))
        self.ratio_entry1 = tk.Entry(self.ratio_frame, width=5)
        self.ratio_entry1.pack(side=tk.LEFT, padx=(0, 2))
        self.vs_label = tk.Label(self.ratio_frame, text="vs")
        self.vs_label.pack(side=tk.LEFT, padx=2)
        self.ratio_entry2 = tk.Entry(self.ratio_frame, width=5)
        self.ratio_entry2.pack(side=tk.LEFT, padx=(2, 5))
        self.ratio_confirm_btn = tk.Button(
            self.ratio_frame,
            text="确定",
            command=self.search_col,
            width=5,
            height=1
        )
        self.ratio_confirm_btn.pack(side=tk.LEFT)
        self.ratio_entry1.bind('<Return>', lambda event: self.search_col())  # 绑定回车键事件
        self.ratio_entry2.bind('<Return>', lambda event: self.search_col())  # 绑定回车键事件

        # 2.修正计算区域
        self.correction_frame = tk.Frame(self.buttons_frame, bd=2, relief=tk.GROOVE)
        self.correction_frame.pack(pady=(5, 0), padx=10, fill=tk.X)
        self.correction_label = tk.Label(self.correction_frame, text="修正计算")
        self.correction_label.pack(anchor=tk.W, pady=(0, 5))
        # 2.1.装备优势
        self.equipment_frame = tk.Frame(self.correction_frame)
        self.equipment_frame.pack(fill=tk.X, pady=(0, 5))
        self.equipment_label = tk.Label(self.equipment_frame, text="装备优势:")
        self.equipment_label.pack(side=tk.LEFT, padx=(0, 10))
        self.equipment_var = tk.StringVar(value="0")
        self.equipment_menu = ttk.Combobox(
            self.equipment_frame,
            textvariable=self.equipment_var,
            values=[str(i) for i in range(-3, 4)],
            state="readonly",
            width=5
        )
        self.equipment_menu.pack(side=tk.LEFT)
        self.equipment_menu.bind("<<ComboboxSelected>>", lambda event: self.search_col())
        # 2.2.地形优势
        self.terrain_frame = tk.Frame(self.correction_frame)
        self.terrain_frame.pack(fill=tk.X, pady=(0, 5))
        self.terrain_label = tk.Label(self.terrain_frame, text="地形优势:")
        self.terrain_label.pack(side=tk.LEFT, padx=(0, 10))
        self.terrain_var = tk.StringVar(value="0")
        self.terrain_menu = ttk.Combobox(
            self.terrain_frame,
            textvariable=self.terrain_var,
            values=[str(i) for i in range(-3, 4)],
            state="readonly",
            width=5
        )
        self.terrain_menu.pack(side=tk.LEFT)
        self.terrain_menu.bind("<<ComboboxSelected>>", lambda event: self.search_col())
        # 2.3.疲劳等级
        self.fatigue_frame = tk.Frame(self.correction_frame)
        self.fatigue_frame.pack(fill=tk.X, pady=(0, 5))
        self.fatigue_label = tk.Label(self.fatigue_frame, text="疲劳等级:")
        self.fatigue_label.pack(side=tk.LEFT, anchor=tk.N, padx=(0, 10))
        # 进攻方疲劳
        self.attack_fatigue_subframe = tk.Frame(self.fatigue_frame)
        self.attack_fatigue_subframe.pack(fill=tk.X, pady=(0, 5))
        self.attack_fatigue_var = tk.StringVar(value="0")
        self.attack_fatigue_label = tk.Label(self.attack_fatigue_subframe, text="进攻:", width=5)
        self.attack_fatigue_label.pack(side=tk.LEFT, padx=(0, 5))
        self.attack_fatigue_menu = ttk.Combobox(
            self.attack_fatigue_subframe,
            textvariable=self.attack_fatigue_var,
            values=["0", "1", "2", "3"],
            state="readonly",
            width=5
        )
        self.attack_fatigue_menu.pack(side=tk.LEFT, padx=(0, 10))
        self.attack_fatigue_menu.bind("<<ComboboxSelected>>", lambda event: self.search_col())
        # 防守方疲劳
        self.defense_fatigue_subframe = tk.Frame(self.fatigue_frame)
        self.defense_fatigue_subframe.pack(fill=tk.X, pady=(5, 0))
        self.defense_fatigue_var = tk.StringVar(value="0")
        self.defense_fatigue_label = tk.Label(self.defense_fatigue_subframe, text="防守:", width=5)
        self.defense_fatigue_label.pack(side=tk.LEFT, padx=(0, 5))
        self.defense_fatigue_menu = ttk.Combobox(
            self.defense_fatigue_subframe,
            textvariable=self.defense_fatigue_var,
            values=["0", "1", "2", "3"],
            state="readonly",
            width=5
        )
        self.defense_fatigue_menu.pack(side=tk.LEFT)
        self.defense_fatigue_menu.bind("<<ComboboxSelected>>", lambda event: self.search_col())

        # 3.裁决分析
        self.analysis_frame = tk.Frame(self.buttons_frame)
        self.analysis_frame.pack(pady=(10, 5), padx=10, fill=tk.X)
        self.analysis_btn = tk.Button(
            self.analysis_frame,
            text="裁决分析",
            command=self.analyze_btn_click,
            width=10,
            height=1
        )
        self.analysis_btn.pack(side=tk.LEFT, padx=(0, 5))

        # 4.随机数
        self.random_frame = tk.Frame(self.buttons_frame)
        self.random_frame.pack(pady=10, padx=10, fill=tk.X)
        self.random_btn = tk.Button(
            self.random_frame, 
            text="生成随机数", 
            command=self.random_btn_click, 
            width=10, 
            height=1
        )
        self.random_btn.pack(side=tk.LEFT, padx=(0, 5))
        self.random_entry = tk.Entry(self.random_frame, width=10)
        self.random_entry.pack(side=tk.LEFT, padx=(0, 5))
        self.random_entry.bind('<Return>', lambda event: self.search_row())
        self.confirm_btn = tk.Button(
            self.random_frame, 
            text="确定", 
            command=self.search_row, 
            width=5, 
            height=1
        )
        self.confirm_btn.pack(side=tk.LEFT)

    def welcome_message(self):
        self.b_text.insert(tk.END, "欢迎使用《“锋衡”手工兵棋推演裁决管理使用一体化系统》")
        self.b_text.insert(tk.END, "\n作者：余秋伟")
        self.b_text.insert(tk.END, "\n联系方式：15399220084")
        self.b_text.insert(tk.END, "\nGitee: https://gitee.com/truewell/auto-judgment")
        self.b_text.insert(tk.END, "\n==========================================================")
        self.b_text.insert(tk.END, "\n\n请先点击右上角按钮导入裁决表")

#### 主界面中workflow相关事件 ##################################################

    def update_step(self):
        """
        在点击“上一步”和“下一步”时，对界面进行的更新：
        1.workflow图像的更新
        2.读取当前步骤描述中“《》”和“<>”内的内容，进行对应的切换
        """
        
        ###### workflow图像的更新 ######
        self.workflow.plot_workflow()
        self.canvas.draw()
        

        ###### 读取当前步骤描述中"《》"和"<>"内的内容，进行对应的切换 ######
        # 清除所有frame的高亮
        frame_list = [
            self.ratio_frame,
            self.equipment_frame,
            self.terrain_frame,
            self.fatigue_frame,
            self.random_frame
        ]
        for frame in frame_list:
            frame.config(bd=0, relief=tk.FLAT, highlightbackground='SystemButtonFace', highlightthickness=0)  # 恢复默认边框
        
        # 获取当前步骤描述
        current_step_text = self.workflow.step_descriptions[self.workflow.current_step]
        
        # 提取尖括号内的内容并高亮对应区域
        match1 = re.search(r'<(.*?)>', current_step_text)
        if match1:
            bracket_content = match1.group(1)
            # 根据内容查找对应的frame
            if '兵力比' in bracket_content:
                target_frame = self.ratio_frame
            elif '装备优势' in bracket_content:
                target_frame = self.equipment_frame
            elif '地形优势' in bracket_content:
                target_frame = self.terrain_frame
            elif '疲劳等级' in bracket_content:
                target_frame = self.fatigue_frame
            elif '生成随机数' in bracket_content:
                target_frame = self.random_frame
            else:
                target_frame = None
            # 设置红色实线边框
            if target_frame:
                target_frame.config(bd=2, relief=tk.SOLID, highlightbackground='red', highlightthickness=2)

        # 提取当前步骤标签中《》内的内容并切换裁决表标签
        match2 = re.search(r'《(.*?)》', current_step_text)
        if match2:
            table_name = match2.group(1)
            # 查找并切换到对应的标签页
            found = False
            for i, tab in enumerate(self.notebook.tabs()):
                tab_text = self.notebook.tab(i, "text")
                if table_name in tab_text:
                    self.notebook.select(i)
                    self.current_table = self.sheet_tables[tab_text]
                    # self.b_text.insert(tk.END, f"\n切换到{tab_text}")
                    # self.b_text.see(tk.END)
                    found = True
                    break
            if not found:
                self.b_text.see(tk.END)

    def workflow_menu_change(self, event=None):
        
        # 切换流程
        self.workflow.update(current_workflow=self.workflow_var.get(), current_step=0)

        # 初始化条件输入
        if hasattr(self, 'current_table') and self.current_table:
            self.current_table.highlight_column('')  # 初始化单元格样式
        self.ratio_entry1.delete(0, tk.END)  # 清空兵力比输入框1
        self.ratio_entry2.delete(0, tk.END)  # 清空兵力比输入框2
        self.equipment_var.set("0")  # 重置装备优势
        self.terrain_var.set("0")  # 重置地形优势
        self.attack_fatigue_var.set("0")  # 重置进攻疲劳
        self.defense_fatigue_var.set("0")  # 重置防守疲劳
        self.random_entry.delete(0, tk.END)  # 清空随机数输入框
        self.current_col_index = -1  # 重置检索结果列

        self.update_step()
        self.b_text.insert(tk.END, f"\n\n切换到{self.workflow.current_workflow}")
        self.b_text.see(tk.END)
               
    def prev_button_click(self):
        # 上一步按钮功能
        if self.workflow.current_step > 0:
            self.workflow.current_step -= 1
            self.update_step()
        else:
            messagebox.showinfo("提示", "已经是第一步，无法再返回")

    def next_button_click(self):
        # 下一步按钮功能
        if self.workflow.current_step < self.workflow.total_steps - 1:
            self.workflow.current_step += 1
            self.update_step()
        else:
            messagebox.showinfo("提示", "已经是最后一步，无法再前进")

    # == 子界面：wokflow management ======================================

    def manage_workflow(self):
        # 创建流程管理窗口
        self.workflow_window = tk.Toplevel(self.root)
        self.workflow_window.title("流程管理")
        self.workflow_window.geometry("600x400")
        
        ######################################## 左侧列表框 ##########################################

        self.workflow_listbox = tk.Listbox(self.workflow_window, width=20)
        self.workflow_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        # 填充列表框
        for workflow_name in self.workflow.dict.keys():
            self.workflow_listbox.insert(tk.END, workflow_name)
        # 绑定列表项选择事件
        self.workflow_listbox.bind("<<ListboxSelect>>", self.workflow_listbox_select)
        
        ######################################## 右侧面板 ############################################
        
        self.right_panel = tk.Frame(self.workflow_window)
        self.right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 流程名称标签和输入框
        tk.Label(self.right_panel, text="流程名称:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.workflow_name_entry = tk.Entry(self.right_panel, width=30)
        self.workflow_name_entry.grid(row=0, column=1, pady=5)
        
        # 步骤列表标签
        tk.Label(self.right_panel, text="步骤列表:").grid(row=1, column=0, sticky=tk.NW, pady=5)
        
        # 步骤列表文本框
        self.steps_text = scrolledtext.ScrolledText(self.right_panel, width=30, height=10)
        self.steps_text.grid(row=1, column=1, padx=(20, 0), pady=5)
        
        ########################################## 按钮区域 ###########################################

        self.buttons_frame = tk.Frame(self.right_panel)
        self.buttons_frame.grid(row=2, column=0, columnspan=2, pady=10)
        
        self.add_button = tk.Button(self.buttons_frame, text="添加流程", command=self.add_button_click)
        self.add_button.pack(side=tk.LEFT, padx=5)
        self.update_button = tk.Button(self.buttons_frame, text="更新流程", command=self.update_button_click)
        self.update_button.pack(side=tk.LEFT, padx=5)
        self.delete_button = tk.Button(self.buttons_frame, text="删除流程", command=self.delete_button_click)
        self.delete_button.pack(side=tk.LEFT, padx=5)
        self.save_button = tk.Button(self.buttons_frame, text="保存流程", command=self.save_button_click)
        self.save_button.pack(side=tk.LEFT, padx=5)

    def workflow_listbox_select(self, event):
        # 获取选中的流程名
        selection = self.workflow_listbox.curselection()
        if selection:
            index = selection[0]
            workflow_name = self.workflow_listbox.get(index)
            
            # 填充到输入框
            self.workflow_name_entry.delete(0, tk.END)
            self.workflow_name_entry.insert(0, workflow_name)
            
            # 填充步骤列表
            self.steps_text.delete(1.0, tk.END)
            steps = self.workflow.dict[workflow_name]
            for step in steps:
                self.steps_text.insert(tk.END, step + "\n")

    def add_button_click(self):
        # 获取输入的流程名和步骤
        workflow_name = self.workflow_name_entry.get().strip()
        steps_text = self.steps_text.get(1.0, tk.END).strip()
        
        if not workflow_name or not steps_text:
            messagebox.showerror("错误", "流程名称和步骤不能为空")
            return
        
        if workflow_name in self.workflow.dict:
            messagebox.showerror("错误", "流程名称已存在")
            return
        
        # 解析步骤列表
        steps = [step.strip() for step in steps_text.split("\n") if step.strip()]
        
        # 添加到流程字典
        self.workflow.dict[workflow_name] = steps
        
        # 更新列表框
        self.workflow_listbox.insert(tk.END, workflow_name)
        
        # 刷新流程选择下拉菜单
        self.workflow_menu['values'] = list(self.workflow.dict.keys())
        
        messagebox.showinfo("成功", f"流程 '{workflow_name}' 添加成功")

    def update_button_click(self):
        # 获取选中的流程名
        selection = self.workflow_listbox.curselection()
        if not selection:
            messagebox.showerror("错误", "请先选择要更新的流程")
            return
        
        index = selection[0]
        old_name = self.workflow_listbox.get(index)
        new_name = self.workflow_name_entry.get().strip()
        steps_text = self.steps_text.get(1.0, tk.END).strip()
        
        if not new_name or not steps_text:
            messagebox.showerror("错误", "流程名称和步骤不能为空")
            return
        
        # 解析步骤列表
        steps = [step.strip() for step in steps_text.split("\n") if step.strip()]
        
        # 更新流程字典
        if old_name != new_name:
            # 如果名称改变，先删除旧名称
            del self.workflow.dict[old_name]
        
        self.workflow.dict[new_name] = steps
        
        # 更新列表框
        self.workflow_listbox.delete(index)
        self.workflow_listbox.insert(index, new_name)
        
        # 刷新流程选择下拉菜单
        self.workflow_menu['values'] = list(self.workflow.dict.keys())
        
        messagebox.showinfo("成功", f"流程 '{new_name}' 更新成功")

    def delete_button_click(self):
        # 获取选中的流程名
        selection = self.workflow_listbox.curselection()
        if not selection:
            messagebox.showerror("错误", "请先选择要删除的流程")
            return
        
        index = selection[0]
        workflow_name = self.workflow_listbox.get(index)

        # 确认删除
        if messagebox.askyesno("确认", f"确定要删除流程 '{workflow_name}' 吗?"):
            # 从字典中删除
            del self.workflow.dict[workflow_name]
            
            # 从列表框中删除
            self.workflow_listbox.delete(index)
            
            # 刷新流程选择下拉菜单
            self.workflow_menu['values'] = list(self.workflow.dict.keys())
            
            # 如果当前使用的流程被删除，切换到第一个可用流程
            if workflow_name == self.workflow.current_workflow:
                if self.workflow.dict:
                    self.workflow.current_workflow = next(iter(self.workflow.dict.keys()))
                    self.workflow.current_step = 0
                    self.workflow.update(
                        current_workflow=self.workflow.current_workflow,
                        current_step=self.workflow.current_step
                    )
                    self.workflow_var.set(self.workflow.current_workflow)
                    self.update_step()
                else:
                    # 如果没有流程了，显示错误
                    self.workflow.current_workflow = ""
                    self.workflow.step_descriptions = []
                    self.workflow.total_steps = 0
                    self.workflow.current_step = 0
                    self.update_step(
                        current_workflow=self.workflow.current_workflow,
                        current_step=self.workflow.current_step
                    )
                    messagebox.showerror("错误", "所有流程已被删除，请添加新流程")
            
            messagebox.showinfo("成功", f"流程 '{workflow_name}' 删除成功")

    def save_button_click(self):
        # 保存流程字典到本地文件
        if self.workflow.save_workflow_dict():
            messagebox.showinfo("成功", "流程已成功保存到本地")
        else:
            messagebox.showerror("错误", "保存流程失败，请检查文件权限")

#### 裁决表相关事件 #############################################################

    def import_btn_click(self):
        # 打开文件选择对话框
        file_path = filedialog.askopenfilename(
            title="选择Excel文件",
            filetypes=[("Excel files", "*.xlsx *.xls")]
        )

        if file_path:
            # 检查文件是否为Excel文件
            _, ext = os.path.splitext(file_path)
            if ext.lower() not in ('.xlsx', '.xls'):
                # 清空所有标签页
                self.clear_all_tabs()
                # 显示错误信息
                self.b_text.delete(1.0, tk.END)
                self.b_text.insert(tk.END, "\n\n错误: 选择的文件不是有效的 Excel 文件（.xlsx 或 .xls）!")
                return

            try:
                # 获取Excel文件的所有sheet名称
                xl = pd.ExcelFile(file_path)
                sheet_names = xl.sheet_names

                # 清空所有标签页
                self.clear_all_tabs()

                # 读取并显示每个sheet的数据
                self.sheets_data = {}
                for sheet_name in sheet_names:
                    # 读取sheet数据
                    df = pd.read_excel(file_path, sheet_name=sheet_name)
                    self.sheets_data[sheet_name] = df

                    # 创建新标签页
                    tab_frame = tk.Frame(self.notebook)
                    self.notebook.add(tab_frame, text=sheet_name)

                    # 在标签页中创建表格
                    table = TableFrame(tab_frame)
                    table.pack(fill=tk.BOTH, expand=True)
                    table.set_data(df)
                    self.sheet_tables[sheet_name] = table

                # 选中第一个标签页
                if sheet_names:
                    self.notebook.select(0)
                    current_sheet = sheet_names[0]
                    self.current_table = self.sheet_tables[current_sheet]
                else:
                    self.current_table = None

                # 在B区显示成功信息
                self.b_text.delete(1.0, tk.END)
                self.b_text.insert(tk.END, f"成功导入裁决表文件: {os.path.basename(file_path)}")
                self.b_text.see(tk.END)

            except (pd.errors.EmptyDataError, pd.errors.ParserError, FileNotFoundError, PermissionError) as e:
                self.clear_all_tabs()
                # 显示错误信息
                self.b_text.insert(tk.END, f"\n\n读取文件时出错: {str(e)}")
                self.b_text.see(tk.END)

        self.blank_label.destroy()  # 删除空白标签

    def clear_all_tabs(self):
        # 清空所有标签页
        for tab in self.notebook.tabs():
            self.notebook.forget(tab)
        # 清空存储
        self.sheets_data = {}
        self.sheet_tables = {}
        self.current_table = None

    def notebook_changed(self, event=None):
        # 获取当前选中的标签页索引
        current_tab_index = self.notebook.select()
        if current_tab_index:
            # 获取所有标签页
            tabs = self.notebook.tabs()
            # 找到当前标签页的索引
            for i, tab in enumerate(tabs):
                if tab == current_tab_index:
                    # 获取当前标签页的文本
                    current_sheet = self.notebook.tab(i, "text")
                    # 更新当前表格
                    self.current_table = self.sheet_tables[current_sheet]
                    # 在B区显示切换信息
                    # self.b_text.insert(tk.END, f"\n切换到{current_sheet}")
                    # self.b_text.see(tk.END)
                    break

#### 裁决条件输入相关事件 ########################################################
    
    def search_col(self):
        if not hasattr(self, 'current_table') or not self.current_table:
            self.b_text.insert(tk.END, "\n\n没有表格数据")
            self.b_text.see(tk.END)
            return
        # self.reset_column_styles()  # 重置所有单元格样式

        # 获取兵力比
        ratio1 = self.ratio_entry1.get().strip()
        ratio2 = self.ratio_entry2.get().strip()
        if not ratio1 or not ratio2:
            self.b_text.insert(tk.END, "\n\n请输入完整的兵力比")
            self.b_text.see(tk.END)
            return
        ratio_text = f"{ratio1}:{ratio2}"  # 组合成X:Y格式
        try:
            self.current_col_index = self.current_table.columns.index(ratio_text)  # 由兵力比获取列索引
        except:
            self.b_text.insert(tk.END, f"\n\n兵力比检索错误")
            return

        # 获取装备优势
        equipment_advantage = int(self.equipment_var.get())

        # 获取地形优势
        terrain_advantage = int(self.terrain_var.get())

        # 获取疲劳等级
        attack_fatigue = int(self.attack_fatigue_var.get())
        defense_fatigue = int(self.defense_fatigue_var.get())

        self.current_col_index += equipment_advantage  # 装备优势修正
        self.current_col_index += terrain_advantage  # 地形优势修正
        self.current_col_index -= attack_fatigue  # 进攻疲劳等级修正
        self.current_col_index += defense_fatigue  # 防守疲劳等级修正

        # 确保新索引在有效范围内
        self.current_col_index = max(1, min(self.current_col_index, len(self.current_table.columns) - 1))

        # 获取新的列名
        new_col_name = self.current_table.columns[self.current_col_index]

        # 高亮新的列
        self.current_table.highlight_column(new_col_name)
        # self.check_highlight_intersection()

    def search_row(self):
        
        index_text = self.random_entry.get().strip()  # 获取随机数

        if not index_text:
            # self.b_text.delete(1.0, tk.END)
            self.b_text.insert(tk.END, "\n\n请输入有效的整数随机数")
            self.b_text.see(tk.END)
            return

        if not hasattr(self, 'current_table') or not self.current_table or not self.current_table.row_frames:
            # self.b_text.delete(1.0, tk.END)
            self.b_text.insert(tk.END, "\n\n没有表格数据")
            self.b_text.see(tk.END)
            return

        try:
            index = int(index_text)
            # 检查索引是否有效
            if index < 1 or index > len(self.current_table.row_frames):
                # self.b_text.delete(1.0, tk.END)
                self.b_text.insert(tk.END, f"\n\n随机数必须在1到{len(self.current_table.row_frames)}之间")
                self.b_text.see(tk.END)
                return

            # 清除所有红色高亮，但保留黄色高亮
            for row_idx, row_frame in enumerate(self.current_table.row_frames):
                # 为行设置交替背景色
                default_bg = '#ffffff' if row_idx % 2 == 0 else '#f9f9f9'
                for cell in row_frame.winfo_children():
                    current_bg = cell.cget('bg')
                    # 只清除红色高亮，保留黄色高亮
                    if current_bg == 'red' and current_bg != self.current_table.highlight_color:
                        cell.config(bg=default_bg)

            # 高亮指定行的所有单元格
            row_frame = self.current_table.row_frames[index - 1]
            for cell in row_frame.winfo_children():
                # 保留黄色高亮
                current_bg = cell.cget('bg')
                if current_bg != self.current_table.highlight_color:
                    cell.config(bg='red')

            # 检查是否有交叉高亮的单元格并输出内容
            self.search_cell(index - 1)
        except ValueError:
            # self.b_text.delete(1.0, tk.END)
            self.b_text.insert(tk.END, "\n\n请输入有效的整数随机数")
            self.b_text.see(tk.END)

    def search_cell(self, row_index=None):
        # 检查是否有列被高亮
        if not hasattr(self, 'current_table') or not self.current_table or self.current_table.highlighted_col_index == -1:
            return


        col_index = self.current_table.highlighted_col_index
        highlighted_row_index = row_index

        # 如果没有提供行索引，尝试查找被红色高亮的行
        if highlighted_row_index is None:
            for r_idx, row_frame in enumerate(self.current_table.row_frames):
                for cell in row_frame.winfo_children():
                    if cell.cget('bg') == 'red':
                        highlighted_row_index = r_idx
                        break
                if highlighted_row_index is not None:
                    break

        # 如果找到了交叉点
        if highlighted_row_index is not None and 0 <= highlighted_row_index < len(self.current_table.row_frames):
            try:
                # 重新更新黄色列高亮
                col_name = self.current_table.columns[col_index]
                self.current_table.highlight_column(col_name)

                # 重新更新红色行高亮
                row_frame = self.current_table.row_frames[highlighted_row_index]
                for cell in row_frame.winfo_children():
                    # 保留黄色高亮
                    current_bg = cell.cget('bg')
                    if current_bg != self.current_table.highlight_color:
                        cell.config(bg='red')

                # 将交叉单元格设置为紫色
                cell = row_frame.grid_slaves(row=0, column=col_index)[0]
                cell.config(bg='purple')
                cell_value = cell.cget('text')

                # 输出交叉点信息
                self.b_text.insert(tk.END, f"\n\n裁决表索引结果: {cell_value}")
                self.b_text.see(tk.END)
                self.b_text.insert(tk.END, f"\n\n==============================")
                self.b_text.see(tk.END)
            except (IndexError, ValueError):
                # 如果发生错误，忽略
                pass

    def random_btn_click(self):
        random_num = func.generate_random()
        self.random_entry.delete(0, tk.END)
        self.random_entry.insert(0, str(random_num))

    def analyze_btn_click(self):
        # 检查是否有当前表格和高亮列
        if not hasattr(self, 'current_table') or not self.current_table or self.current_col_index == -1:
            self.b_text.insert(tk.END, "\n请先选择有效的裁决表列")
            self.b_text.see(tk.END)
            return

        # 获取当前列的索引和名称
        col_index = self.current_table.highlighted_col_index
        col_name = self.current_table.columns[col_index]

        # 提取当前列所有单元格的内容
        casualties_data = []
        for row_frame in self.current_table.row_frames:
            try:
                cell = row_frame.grid_slaves(row=0, column=col_index)[0]
                cell_value = cell.cget('text')
                # 按照"/"拆分单元格内容
                if '/' in cell_value:
                    attack_loss, defense_loss = cell_value.split('/')
                    attack_loss = int(attack_loss.strip())
                    defense_loss = int(defense_loss.strip())
                    casualties_data.append((attack_loss, defense_loss))
            except (IndexError, ValueError):
                # 忽略无效的单元格
                continue

        # 检查是否有有效的战损数据
        if not casualties_data:
            self.b_text.insert(tk.END, f"\n在列 '{col_name}' 中未找到有效的战损数据")
            self.b_text.see(tk.END)
            return

        # 计算进攻方和防守方的战损概率分布和期望值
        attack_losses = [data[0] for data in casualties_data]
        defense_losses = [data[1] for data in casualties_data]

        # 计算进攻方战损概率分布
        attack_counts = {}
        for loss in attack_losses:
            attack_counts[loss] = attack_counts.get(loss, 0) + 1

        attack_prob_dist = {k: v / len(attack_losses) for k, v in attack_counts.items()}
        attack_expectation = sum(k * v for k, v in attack_prob_dist.items())

        # 计算防守方战损概率分布
        defense_counts = {}
        for loss in defense_losses:
            defense_counts[loss] = defense_counts.get(loss, 0) + 1

        defense_prob_dist = {k: v / len(defense_losses) for k, v in defense_counts.items()}
        defense_expectation = sum(k * v for k, v in defense_prob_dist.items())

        # 在裁决输出区域显示结果
        self.b_text.insert(tk.END, f"\n\n=== 裁决分析结果 ({col_name}) ===")
        self.b_text.insert(tk.END, "\n\n进攻方战损分析:")
        self.b_text.insert(tk.END, "\n概率分布:")
        for loss, prob in sorted(attack_prob_dist.items()):
            self.b_text.insert(tk.END, f"\n  {loss}: {prob:.2%}")
        self.b_text.insert(tk.END, f"\n期望值: {attack_expectation:.2f}")

        self.b_text.insert(tk.END, "\n\n防守方战损分析:")
        self.b_text.insert(tk.END, "\n概率分布:")
        for loss, prob in sorted(defense_prob_dist.items()):
            self.b_text.insert(tk.END, f"\n  {loss}: {prob:.2%}")
        self.b_text.insert(tk.END, f"\n期望值: {defense_expectation:.2f}")
        self.b_text.insert(tk.END, "\n\n==============================")
        self.b_text.see(tk.END)
